package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.enums.*;
import cn.huiyunche.base.service.interfaces.*;
import cn.huiyunche.base.service.mappers.SOrderDetailMapper;
import cn.huiyunche.base.service.mappers.SOrderFeedetailMapper;
import cn.huiyunche.base.service.mappers.SOrderMapper;
import cn.huiyunche.base.service.mappers.SOrderVinMapper;
import cn.huiyunche.base.service.model.*;
import cn.huiyunche.base.service.utils.DateUtils;
import cn.huiyunche.base.service.vo.UserVo;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import cn.huiyunche.base.service.utils.UniquenessFlagUnits;
import cn.huiyunche.base.service.vo.SaleBrandVo;
import cn.huiyunche.base.service.vo.SaleOrderVo;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by houjianhui on 2017/6/12.
 */
@Service
public class SalesOrderServiceImpl implements SalesOrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SalesOrderServiceImpl.class);

    private int VINTAG = 0;

    @Autowired
    private SOrderMapper sOrderMapper;

    @Autowired
    private BAreaService bAreaService;

    @Autowired
    private OrderStatusLogService orderStatusLogService;

    @Autowired
    private SOrderDetailMapper detailMapper;

    @Autowired
    private BFeeTypeService bFeeTypeService;

    @Autowired
    private BFeeModelService bFeeModelService;

    @Autowired
    private SOrderFeedetailMapper sOrderFeedetailMapper;


    @Autowired
    private SOrderVinMapper orderVinMapper;

    @Autowired
    private SOrderProductService sOrderProductService;

    @Autowired
    private UserService userService;

    @Autowired
    private SServiceOrderService sServiceOrderService;

    @Autowired
    private SOrderDetailService sOrderDetailService;

    @Autowired
    private SServiceOrderVehicleService sServiceOrderVehicleService;

    @Autowired
    private SServiceOrderFeedetailService sServiceOrderFeedetailService;

    @Autowired
    private SServiceOrderStatusLogService sServiceOrderStatusLogService;

    @Override
    public Long save(SaleOrderVo vo) throws Exception {
        if (Objects.equals(vo, null) || Objects.equals(vo, "")) {
            LOGGER.info("SalesOrderServiceImpl.save SaleOrderVo must not be null");
            throw new IllegalArgumentException("销售订单信息不能为空");
        }

        // 校验数据
        validate(vo);

        // 重复校验
        repeatValidate(vo.getOrderCode());

        SOrder sOrder = new SOrder();
        // 生成订单号
        sOrder.setOrderCode(UniquenessFlagUnits.generateUniquenessFlag("CO"));
        sOrder.setOutOrderCode(vo.getOrderCode());

        // 获取用户信息
        SUser user = userService.getById(Long.valueOf(vo.getUserId()));
        if (Objects.equals(user, null) || Objects.equals(user, "")) {
            LOGGER.info("The current user does not exist userId: {}", vo.getUserId());
            throw new BusinessException("当前用户不存在");
        }
        sOrder.setUserId(Long.valueOf(vo.getUserId()));
        List<BArea> result = new ArrayList<>();
        // 起运地
        buindRegion(result, vo.getDepartRegionCode());
        if (CollectionUtils.isNotEmpty(result)) {
            result.stream().forEach(val -> {
                if (Objects.equals(val.getLevel(), "1")) {
                    sOrder.setDepartProvinceCode(val.getCode());
                    sOrder.setDepartProvinceName(val.getName());
                } else if (Objects.equals(val.getLevel(), "2")) {
                    sOrder.setDepartCityCode(val.getCode());
                    sOrder.setDepartCityName(val.getName());
                } else if (Objects.equals(val.getLevel(), "3")) {
                    sOrder.setDepartCountyCode(val.getCode());
                    sOrder.setDepartCountyName(val.getName());
                }
            });
        }
        sOrder.setDepartContact(vo.getDepartContact());
        sOrder.setDepartPhone(vo.getDepartPhone());
        // 目的地
        List<BArea> result1 = new ArrayList<>();
        buindRegion(result1, vo.getDestRegionCode());
        if (CollectionUtils.isNotEmpty(result1)) {
            result1.stream().forEach(val -> {
                if (Objects.equals(val.getLevel(), "1")) {
                    sOrder.setReceiptProvinceCode(val.getCode());
                    sOrder.setReceiptProvinceName(val.getName());
                } else if (Objects.equals(val.getLevel(), "2")) {
                    sOrder.setReceiptCityCode(val.getCode());
                    sOrder.setReceiptCityName(val.getName());
                } else if (Objects.equals(val.getLevel(), "3")) {
                    sOrder.setReceiptCountyCode(val.getCode());
                    sOrder.setReceiptCountyName(val.getName());
                }
            });
        }
        sOrder.setReceiptContact(vo.getDestContact());
        sOrder.setReceiptPhone(vo.getDepartPhone());
        sOrder.setDeliveryDate(DateUtils.StrToDate(vo.getPickDate(), "yyyy-MM-dd"));
        sOrder.setAmount(vo.getSeriesAmt());
        sOrder.setDistance(new BigDecimal(StringUtils.isBlank(vo.getDistance()) ? "0" : vo.getDistance()));
        sOrder.setOrderCost(new BigDecimal(StringUtils.isBlank(vo.getOrderCost()) ? "0" : vo.getOrderCost()));
        sOrder.setActualCost(new BigDecimal(StringUtils.isBlank(vo.getOrderCost()) ? "0" : vo.getOrderCost()));
        sOrder.setComment(vo.getComment());
        sOrder.setStatus(Integer.valueOf(COrderStatusEnum.SAVED.getValue()));
        sOrder.setPayStatus(Integer.valueOf(PaymentStatusEnum.UNPAID.getValue()));
        sOrder.setOrderType(OrderTypeEnum.ENTERPRISE.getValue());
        try {
            sOrderMapper.insertSelective(sOrder);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.save Order error: {}", e);
            throw new BusinessException("保存订单信息异常");
        }

        //保存客户订单和物流产品关联信息
        try {
            sOrderProductService.add(sOrder.getId(), 2, null);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.save OrderProduct error: {}", e);
            throw new BusinessException("保存客户订单和物流产品关联信息异常");
        }

        long orderId = sOrder.getId().longValue();
        UserVo userVo = new UserVo(user.getId(), user.getName(), null, null, true, null);

        try {
            orderStatusLogService.insertSelective(orderId, StatusCategoryEnum.PROCESS, COrderStatusEnum.SAVED, false, userVo);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.save OrderStatusLog error: {}", e);
            throw new BusinessException("保存订单状态日志信息异常");
        }


        // 订单明细
        List<SaleBrandVo> brandVos = JSONArray.parseArray(vo.getOrderSku(), SaleBrandVo.class);
        if (CollectionUtils.isNotEmpty(brandVos)) {
            brandVos.stream().forEach(val -> {
                SOrderDetail detail = new SOrderDetail();
                detail.setOrderId(sOrder.getId());
                detail.setAmount(Objects.equals(val.getAmt(), null) ? 0 : val.getAmt());
                detail.setBrandId(Long.valueOf(val.getBrandId()));
                detail.setBrandName(val.getBrandName());
                detail.setVehicleId(Long.valueOf(val.getSeriesId()));
                detail.setVehicleName(val.getSeriesName());
                try {
                    detailMapper.insertSelective(detail);
                } catch (Exception e) {
                    LOGGER.error("SalesOrderServiceImpl.save SOrderDetail error: {}", e);
                    throw new BusinessException("保存订单明细信息异常");
                }
                saveOrderVin(val.getAmt(), sOrder.getId(), detail.getId(), sOrder.getOrderCode(), VINTAG);
            });
            VINTAG = 0;
        }

        // 订单费用
        BFeeTypeEnum[] var1 = BFeeTypeEnum.values();
        for(int var3 = 0; var3 < var1.length; ++var3) {
            BFeeTypeEnum temp = var1[var3];
            if (BFeeTypeEnum.STARTING_PRICE.getValue() != temp.getValue() && BFeeTypeEnum.KM.getValue() != temp.getValue() && BFeeTypeEnum.TRAILER.getValue() != temp.getValue()) {
                queryFees(sOrder.getOrderCost(), new BigDecimal(StringUtils.isBlank(vo.getBxCost()) ? "0" : vo.getBxCost()), temp.getValue(), sOrder.getId());
            }
        }

        // 发布订单
        publish(sOrder.getId(), vo.getBxCost(), userVo);
        return sOrder.getId();
    }

    @Override
    public Long save(String saleOrder) throws Exception {
        if (StringUtils.isBlank(saleOrder)){
            throw new BusinessException("销售订单信息不能为空");
        }
        List<SaleOrderVo> saleOrderVos = JSONArray.parseArray(saleOrder, SaleOrderVo.class);
        if (CollectionUtils.isNotEmpty(saleOrderVos)) {
            for (int i = 0; i < saleOrderVos.size(); i++) {
                save(saleOrderVos.get(i));
            }
        }
        return null;
    }

    @Override
    public String getOrderStatus(String orderCode) throws Exception {
        if (StringUtils.isBlank(orderCode)) {
            return null;
        }

        String[] orderCodes = orderCode.split(",");
        SOrderExample example = new SOrderExample();
        example.createCriteria().andOutOrderCodeIn(Arrays.asList(orderCodes));
        List<SOrder> sOrders = sOrderMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(sOrders)) {
            List<String> list = new ArrayList<>();
            sOrders.stream().forEach(val -> {
                String code_status = val.getOutOrderCode() + ",";
                // 10, "待接单" 30, "待支付"  --待接单
                Integer status = val.getStatus();
                if (COrderStatusEnum.WAIT_RECEIVE.getValue() == status || COrderStatusEnum.CONFIRMED.getValue() == status) {
                    code_status = code_status + 20;
                } else if (COrderStatusEnum.IN_TRANSIT.getValue() == status || 50 == status || 60 == status || 70 == status) {//40, "执行中"  50, "已提车" 60, "已发车"  70, "运输中" --已接单
                    code_status = code_status + 30;
                } else if (COrderStatusEnum.COMPLETED.getValue() == status) { // 80 已交车
                    code_status = code_status + 40;
                } else if (COrderStatusEnum.DONE.getValue() == status) { // 90 已交车
                    if (PaymentStatusEnum.ALREADY_PAID.getValue() == val.getPayStatus()) { // 已付款30 -- 已收款
                        code_status = code_status + 50;
                    } else {
                        code_status = code_status + 40;
                    }
                }
                list.add(code_status);
            });
            return JSONObject.toJSONString(list);
        }
        return null;
    }


    public void buindRegion(List<BArea> result, String code) throws Exception{
        if (StringUtils.isNotBlank(code)) {
            List<BArea> areas = bAreaService.selectAreaByCode(code);
            if (CollectionUtils.isNotEmpty(areas)) {
                BArea bArea = areas.get(0);
                result.add(bArea);
                buindRegion(result, bArea.getParentCode());
            }
        }
    }

    private void queryFees(BigDecimal ysf, BigDecimal bxf, Integer bFeeType, Long orderId) throws Exception {
        BFeeType var1 = bFeeTypeService.getByCode(bFeeModelService.getByCode(BFeeModelEnum.INTERCITY_ORDER).getId(), Arrays.asList(new Integer[]{BFeeTypeEnum.getByValue(bFeeType).getValue()})).get(0);
        SOrderFeedetail var2 = new SOrderFeedetail();
        var2.setFeeCode(var1.getFeeCode());
        var2.setFeeName(var1.getFeeName());
        var2.setOrderId(orderId);
        var2.setFeeTypeId(var1.getId());
        if (BFeeTypeEnum.SHIPPING.getValue() == bFeeType) {
            var2.setMoney(ysf);
            var2.setActualAmount(ysf);
        } else if (BFeeTypeEnum.INSURANCE.getValue() == bFeeType) {
            var2.setMoney(bxf);
            var2.setActualAmount(bxf);
        } else {
            var2.setMoney(new BigDecimal(0.00));
            var2.setActualAmount(new BigDecimal(0.00));
        }
        try {
            sOrderFeedetailMapper.insertSelective(var2);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.save SOrderFeedetail error: {}", e);
            throw new BusinessException("保存订单价格信息异常");
        }
    }

    private void saveOrderVin(Integer amt, Long orderId, Long orderDetailId, String orderCode, Integer ii) {
        if (amt > 0) {
            for (int i = 0; i < amt; i ++) {
                SOrderVin vin = new SOrderVin();
                vin.setOrderId(orderId);
                vin.setDetailId(orderDetailId);
                String vins = orderCode.substring(4, orderCode.length()) + "" + VINTAG;
                vin.setVin(vins);
                try {
                    orderVinMapper.insertSelective(vin);
                } catch (Exception e) {
                    LOGGER.error("SalesOrderServiceImpl.save SOrderVin error: {}", e);
                    throw new BusinessException("保存订单VIN信息异常");
                }
                VINTAG ++;
            }
        }
    }

    private void publish(long orderid, String bxCost, UserVo userVo) throws Exception {
        SOrderExample search = new SOrderExample();
        search.createCriteria().andStatusEqualTo(COrderStatusEnum.SAVED.getValue()).andIdEqualTo(orderid);
        List<SOrder> orders = sOrderMapper.selectByExample(search);
        if (CollectionUtils.isEmpty(orders)) {
            LOGGER.error("orders is empty");
            throw new BusinessException("发布失败！");
        }
        SOrder order = orders.get(0);
        order.setStatus(COrderStatusEnum.WAIT_RECEIVE.getValue());
        try {
            sOrderMapper.updateByPrimaryKeySelective(order);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.publish SOrder error: {}", e);
            throw new BusinessException("更新订单状态信息异常");
        }


        buildServiceOrder(order, bxCost);

        try {
            orderStatusLogService.insertSelective(orderid, StatusCategoryEnum.PROCESS, COrderStatusEnum.WAIT_RECEIVE,
                    false, userVo);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.publish orderStatusLog error: {}", e);
            throw new BusinessException("保存订单状态日志信息异常");
        }
    }

    private List<SOrderVin> getList(long customerOrderId) {
        SOrderVinExample example = new SOrderVinExample();
        example.createCriteria().andOrderIdEqualTo(customerOrderId);
        List<SOrderVin> list = orderVinMapper.selectByExample(example);
        if (org.springframework.util.CollectionUtils.isEmpty(list)) {
            LOGGER.error("getList list is empty");
            throw new BusinessException("获取客户订单车架号信息失败！");
        }
        return list;
    }

    private void buildServiceOrder(SOrder order, String bxCost) throws Exception {
        SServiceOrder sOrder = new SServiceOrder();
        SOrderVin vin;
        List<SOrderVin> vins = getList(order.getId());
        List<SServiceOrderStatusLog> statusList = new ArrayList<>();
        SUser user = userService.getById(order.getUserId());
        BigDecimal cost = order.getOrderCost().divide(BigDecimal.valueOf(vins.size())).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bx = BigDecimal.valueOf(Double.valueOf(StringUtils.isBlank(bxCost)?"0":bxCost)).divide(BigDecimal.valueOf(vins.size()).setScale(2, BigDecimal.ROUND_HALF_UP));
        for (int i = 0; i < vins.size(); i++) {
            BeanUtils.copyProperties(order, sOrder);
            vin = vins.get(i);
            sOrder.setStatus(SServiceOrderStatusEnum.WAIT_DISPATCH.getValue());
            sOrder.setDispatchTimes(0);//调度次数默认0
            sOrder.setEstValue(vin.getEstValue());
            sOrder.setCustomerOrderId(order.getId());
            sOrder.setCost(cost);
            sOrder.setAmount(1);
            sOrder.setOrderCode(UniquenessFlagUnits.generateUniquenessFlag("SO"));
            sOrder.setCurrentAddr(order.getDepartCityName());
            sOrder.setIsVeneer(order.getIsVeneer());
            try {
                sServiceOrderService.add(sOrder);
            } catch (Exception e) {
                LOGGER.error("SalesOrderServiceImpl.buildServiceOrder SServiceOrder error: {}", e);
                throw new BusinessException("保存服务订单信息异常");
            }

            SOrderDetail detail = sOrderDetailService.getById(vin.getDetailId());

            //保存服务订单车辆信息
            SServiceOrderVehicle vehicle = new SServiceOrderVehicle();
            vehicle.setServiceOrderId(sOrder.getId());
            vehicle.setBrandId(detail.getBrandId());
            vehicle.setVehicleId(detail.getVehicleId());
            vehicle.setVin(vin.getVin());
            vehicle.setSysVehicleClassid(detail.getSysVehicleClassid());
            vehicle.setSysVehicleClass(detail.getSysVehicleClass());

            try {
                sServiceOrderVehicleService.add(vehicle);
            } catch (Exception e) {
                LOGGER.error("SalesOrderServiceImpl.buildServiceOrder SServiceOrderVehicle error: {}", e);
                throw new BusinessException("保存服务订单车辆信息异常");
            }

            // 订单费用
            BFeeTypeEnum[] var1 = BFeeTypeEnum.values();
            for(int var3 = 0; var3 < var1.length; ++var3) {
                BFeeTypeEnum temp = var1[var3];
                if (BFeeTypeEnum.STARTING_PRICE.getValue() != temp.getValue() && BFeeTypeEnum.KM.getValue() != temp.getValue() && BFeeTypeEnum.TRAILER.getValue() != temp.getValue()) {
                    saveServiceOrderFeeDetail(cost, bx, sOrder.getId(), temp.getValue());
                }
            }

            //状态变更
            SServiceOrderStatusLog log = new SServiceOrderStatusLog();
            log.setServiceOrderId(sOrder.getId());
            log.setStatus(sOrder.getStatus());
            log.setUserId(user.getId());
            log.setUserName(user.getName());
            statusList.add(log);
        }

        //保存服务订单状态变更
        try {
            sServiceOrderStatusLogService.batchAdd(statusList);
        } catch (Exception e) {
            LOGGER.error("SalesOrderServiceImpl.buildServiceOrder ServiceOrderStatusLog error: {}", e);
            throw new BusinessException("保存服务订单状态变更信息异常");
        }

    }

    private void saveServiceOrderFeeDetail(BigDecimal ysf, BigDecimal bxf, Long serviceId, Integer bFeeType) {
        BFeeType var1 = bFeeTypeService.getByCode(bFeeModelService.getByCode(BFeeModelEnum.INTERCITY_ORDER).getId(), Arrays.asList(new Integer[]{BFeeTypeEnum.getByValue(bFeeType).getValue()})).get(0);
        BigDecimal money = new BigDecimal(0);
        BigDecimal actualAmount = new BigDecimal(0);
        if (BFeeTypeEnum.SHIPPING.getValue() == bFeeType) {
            money = ysf;
            actualAmount = ysf;
        } else if (BFeeTypeEnum.INSURANCE.getValue() == bFeeType) {
            money = bxf;
            actualAmount = bxf;
        }
        sServiceOrderFeedetailService.addFeeDetail(serviceId, var1.getId(), var1.getFeeName(), money, actualAmount);
    }

    private void validate(SaleOrderVo vo) throws Exception {
        if (Objects.equals(vo.getUserId(), null) ||  Objects.equals(vo.getUserId(), "") || Objects.equals(vo.getUserId(), 0)) {
            LOGGER.info("SalesOrderServiceImpl.save userId must not be null");
            throw new BusinessException("用户ID不能为空");
        } else if (Objects.equals(vo.getDistance(), null) ||  Objects.equals(vo.getDistance(), "") || Objects.equals(vo.getDistance(), 0)) {
            LOGGER.info("SalesOrderServiceImpl.save Distance must not be null");
            throw new BusinessException("运距不能为空");
        } else if (Objects.equals(vo.getBxCost(), null) ||  Objects.equals(vo.getBxCost(), "") ) {
            LOGGER.info("SalesOrderServiceImpl.save BxCost must not be null");
            throw new BusinessException("保险费不能为空");
        } else if (Objects.equals(vo.getDepartContact(), null) ||  Objects.equals(vo.getDepartContact(), "") ) {
            LOGGER.info("SalesOrderServiceImpl.save DepartContact must not be null");
            throw new BusinessException("发车联系人不能为空");
        } else if (Objects.equals(vo.getDepartPhone(), null) ||  Objects.equals(vo.getDepartPhone(), "") ) {
            LOGGER.info("SalesOrderServiceImpl.save DepartPhone must not be null");
            throw new BusinessException("发车人联系电话不能为空");
        } else if (Objects.equals(vo.getDepartRegionCode(), null) ||  Objects.equals(vo.getDepartRegionCode(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save DepartRegionCode must not be null");
            throw new BusinessException("起运地编码不能为空");
        } else if (Objects.equals(vo.getDestContact(), null) ||  Objects.equals(vo.getDestContact(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save DestContact must not be null");
            throw new BusinessException("收车联系人不能为空");
        } else if (Objects.equals(vo.getDestPhone(), null) ||  Objects.equals(vo.getDestPhone(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save DestPhone must not be null");
            throw new BusinessException("收车人联系电话不能为空");
        } else if (Objects.equals(vo.getDestRegionCode(), null) ||  Objects.equals(vo.getDestRegionCode(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save DestRegionCode must not be null");
            throw new BusinessException("目的地编码不能为空");
        } else if (Objects.equals(vo.getPickDate(), null) ||  Objects.equals(vo.getPickDate(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save PickDate must not be null");
            throw new BusinessException("提车时间不能为空");
        } else if (Objects.equals(vo.getOrderSku(), null) ||  Objects.equals(vo.getOrderSku(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save OrderSku must not be null");
            throw new BusinessException("商品车信息不能为空");
        } else if (Objects.equals(vo.getOrderCost(), null) ||  Objects.equals(vo.getOrderCost(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save OrderCost must not be null");
            throw new BusinessException("订单价格不能为空");
        } else if (Objects.equals(vo.getOrderCode(), null) ||  Objects.equals(vo.getOrderCode(), "")) {
            LOGGER.info("SalesOrderServiceImpl.save OrderCode must not be null");
            throw new BusinessException("订单编码不能为空");
        } else if (Objects.equals(vo.getSeriesAmt(), null) ||  Objects.equals(vo.getSeriesAmt(), "") ||  Objects.equals(vo.getSeriesAmt(), 0)) {
            LOGGER.info("SalesOrderServiceImpl.save SeriesAmt must not be null");
            throw new BusinessException("商品车数量不能为空");
        }
    }

    private void repeatValidate(String orderCode) {
        SOrderExample example = new SOrderExample();
        example.createCriteria().andOutOrderCodeEqualTo(orderCode);
        List<SOrder> orders = sOrderMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(orders)) {
            LOGGER.info("SalesOrderServiceImpl.repeatValidate orderCode : {} existing", orderCode);
            throw new BusinessException(orderCode + "订单已存在");
        }
    }



}